package com.gitee.wsl.struct.attribute.pairs


/** Class for constraint definition. Imitates limited interface to [Case].  */
class ConstrainableCase internal constructor(
    /** [Item]s [List] representing possible [Case] to test constraint against. Can be incomplete.  */
    private val items: List<Item?>
) {
    /**
     * Gets [Case] value mapped to [Parameter] name. Designed to use only for defining a constraint.
     *
     *
     * For detailed constraint description and usage see `AllPairs.AllPairsBuilder#withConstraint(Predicate)`.
     *
     * --
     *
     *
     * Implementation details:
     * If [Case] contains no mapping to the [Parameter] name, throws `NoSuchParameterNameException`.
     * When used to define constraint, the Exception is handled internally in `AllPairs#isValidCase(List)`.
     * This could happen when [Case] is incomplete or when a user specified non-existent `Parameter` name.
     * The Exception is used as control flow to allow constraints to be defined as `Predicate`.
     *
     * @param parameterName [Parameter] name mapped to the value to return
     * @return value mapped to the [name][Parameter]
     * @see AllPairs.AllPairsBuilder.withConstraint
     */
    operator fun get(parameterName: String): Any {
        return items
            .filter { item: Item? ->
                item?.name == parameterName
            }
            .firstOrNull()?:throw NO_SUCH_PARAMETER_NAME_EXCEPTION

        /*return items.stream()
            .filter { item: Item ->
                item.name == parameterName
            }
            .findAny()
            .orElseThrow { NO_SUCH_PARAMETER_NAME_EXCEPTION }
            .value*/
    }

    /**
     * Exception to be used as control flow to test constraints.
     *
     *
     * Constructs new [RuntimeException] with fixed detail message, no cause, disabled suppression
     * and no stack trace to cause as little performance penalty as possible.
     */
    internal class NoSuchParameterNameException() : RuntimeException("Case doesn't contain provided key (Parameter#name)")

    companion object {
        // Defined as a constant to cause as little performance penalty as possible
        private val NO_SUCH_PARAMETER_NAME_EXCEPTION = NoSuchParameterNameException()
    }
}